Simulations

Poverty has a lasting impact on children. Growing up in poverty increases stress and incarceration rates and decreases educational and health outcomes. These negative consequences not only impact the nation’s poor, but the entire economy as well–child poverty shrinks GDP by more than $1 trillion annually.

Research has shown that giving money to families with children, as most developed countries do, can reduce each of these issues. Programs that provide cash to families with children are called a child allowance, and are typically paid out on a monthly basis.

This site allows users to explore the impact of a potential child allowance of various amounts in each state. Users can also select between three funding mechanisms:

  • Deficit funded does not impose any new taxes. Note that each of these tax reforms is static and does not account for changes in behavior.

  • Federal tax as a flat rate on taxable income. For each child allowance amount the total cost is calculated by multiplying the annual child allowance by the total number of children. To calculate the revenue neutral tax rate, the total cost is divided by the nation’s total taxable income. For example, a child allowance of $100 per month would cost about $88 billion annually and require a new flat tax of 1.1 percent.

  • State tax as a flat rate on taxable income. The state tax is calculated in the same manner as the federal tax, but at the state level. This shows how states can fund their own child allowances. Because states vary in child population and income, different states have different tax rates. A $100 monthly child allowance in DC is offset by a 0.5 percent tax on taxable income while the same amount requires a 1.3 percent tax in Alabama.

# Imports.
import pandas as pd
import numpy as np
import math
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# Load data.
summary = pd.read_csv('https://github.com/ngpsu22/Child_Allowance_States/raw/main/poverty_gini_tax_child_allowance')

deciles = pd.read_csv('data/deciles.csv')


# General configs.
LABELS = {'monthly_ca': 'Monthly child allowance',
          'decile': 'Decile',
          'net_chg': 'Net change',
          'pct_chg': 'Net change',
          'child_allowance':'Monthly child allowance',
          'code': 'State',
          'state': 'State',
          'fed_tax_rate': 'Tax rate',
          'state_tax_rate': 'Tax rate',
          'non_funded_poverty_rate': 'Poverty rate',
          'fed_poverty_rate': 'Poverty rate',
          'state_poverty_rate': 'Poverty rate',
          'non_funded_gini': 'Gini index',
          'fed_gini': 'Gini index',
          'state_gini': 'Gini index'}

# Preprocess data.
summary.drop('Unnamed: 0', 1, inplace = True)
tax = summary[(summary.race == 'All') & (summary.age_group == 'all')]

state_names = tax.state.unique()
state_names = np.insert(state_names[:-1], 0, 'US')
default_state = 'US'

# Colors from https://material.io/design/color/the-color-system.html
DARK_BLUE = '#1565C0'
LIGHT_BLUE = '#2196F3'
GRAY = '#BDBDBD'
GRAY_SHADOW = '#F5F5F5'
COLOR_MAP = {
    'Federal tax rate': DARK_BLUE,
    'State tax rate': LIGHT_BLUE,
    'Federal tax': DARK_BLUE,
    'State tax': LIGHT_BLUE,
    'No funding': GRAY,
    'No funding, out of poverty': GRAY_SHADOW
}

# data labels
REFORM = {'state_tax_rate': 'State tax rate', 
          'fed_tax_rate': 'Federal tax rate'}

# reformat data
data_list = []
for state in state_names:
    state_data = tax[tax.state == state]
    state_list = []
    for reform in REFORM:
        state_list.append(state_data[reform])
    data_list.append(state_list)

data_columns = list(REFORM.keys())
data = pd.DataFrame(data_list, columns = data_columns)
data['State'] = state_names
data = data.set_index('State')

def getDataList(state):
    data_list = []
    for dc in data_columns:
        data_list.append(data.loc[state][dc])
    return data_list

# initialize figure
fig = go.Figure()

# add traces
x = tax.child_allowance.unique()
for reform in REFORM:
    fig.add_trace(go.Scatter(
        x=x, 
        y=data[reform][default_state],
        name=REFORM[reform],
        marker = dict(color = COLOR_MAP[REFORM[reform]])
    ))

# generate buttons
buttons = []
for state in state_names:
    new_button = {'method': 'update',
                  'label': state,
                  'args': [{'y': getDataList(state), 
                            'visible': ['legendonly' if state == 'US' 
                                        else True, True]},
                           {'title': 'Income tax required to fund child ' +
                            'allowances in ' + state}
                          ]}
    buttons.append(new_button)
    
# construct menus
updatemenus = [{'buttons': buttons,
                'direction': 'down',
                'showactive': True,
                'pad':{'l': 10, 'r': 25},
               }]

# update layout with buttons, and show the figure
fig.update_layout(updatemenus=updatemenus)

fig.update_xaxes(title_text='Monthly child allowance')

tax_values = tax.state_tax_rate.tolist() + tax.fed_tax_rate.tolist() 
ymin = math.floor(min(tax_values) * 100) / 100
ymax = math.ceil(max(tax_values) * 100) / 100
fig.update_yaxes(title_text='Tax rate on taxable income', range=[ymin, ymax])

fig.update_layout(height=600, 
                  margin=dict(l=0, r=0, t=80, b=0),
                  yaxis_ticksuffix='%',
                  font=dict(family='Roboto'),
                  hovermode='x', 
                  xaxis_tickprefix='$',
                  xaxis_ticksuffix='',
                  plot_bgcolor='white',
                  legend_title_text='',
                  title={
                    'text': ('Income tax required to fund child allowances ' +
                             'in ' + default_state),
                    'y':0.95,
                    'x':0.01,
                    'xanchor': 'left',
                    'yanchor': 'top'}
                 )

fig.update_traces(mode='markers+lines', hovertemplate=None)

# hide state tax rate for US only
hide_line = ['State tax rate']
fig.for_each_trace(lambda trace: trace.update(visible="legendonly")
                   if trace.name in hide_line else ())

fig.show(config={'displayModeBar': False})

While the new tax would hit most Americans, save the very poorest who earn less than the standard deduction, the overall distributional consequences would be positive. For instance, the bottom decile would see their average resources rise by ________ per person with a federal $300 per month child allowance while the top 10 percent would see their average resources per person fall by

# make chart symmetric with boundary at the maximum.
boundary = deciles.net_chg.agg([min, max]).abs().max()

# initial data set-up 
x = deciles.decile.unique()
ca_amts = deciles.monthly_ca.unique()
state_names = deciles.state.unique()
state_names = np.insert(state_names[:-1], 0, 'US')
fundings = deciles.funding.unique()

# get list of bar colors
# this matches 'fundings' above
colors = [COLOR_MAP['No funding'], COLOR_MAP['Federal tax'],
          COLOR_MAP['State tax']]

# create figure dictionary
fig_dict = {
    'data': [],
    'layout': {},
    'frames': []
}

# fill in most of layout
fig_dict['layout'] = {
    'plot_bgcolor': 'white',
    'font': dict(family = 'Roboto'),
    'showlegend': True,
    'height': 600,
    'margin': dict(t=100, b=0, l=0, r=0)
}
fig_dict['layout']['title'] = {
    'text': 'Average net change to household income by decile', 
    'y': 0.97,
    'x': 0.05,
    'xanchor': 'left',
    'yanchor': 'top'
}
fig_dict['layout']['xaxis'] = {
    'title': 'Decile of resources per person', 
    'dtick': 1,
    'type': 'category'
}
fig_dict['layout']['yaxis'] = {
    'title': 'Average annual net change per SPM unit', 
    'tickprefix': '$',
    'range': [-boundary, boundary]
}

# add slider specifications
slider_menu =  {
    'buttons': [
        {
            'args': [None, {'frame': {'duration': 500, 'redraw': True},
                            'fromcurrent': True,
                            'transition': {'duration': 300,
                                           'easing': 'quadratic-in-out'}}],
            'label': '▶',
            'method': 'animate'
        },
        {
            "args": [[None], {"frame": {"duration": 0, "redraw": True},
                              "mode": "immediate",
                              "transition": {"duration": 0}}],
            "label": "◼",
            "method": "animate"
        }
    ],
    'direction': 'left',
    'pad': {'r': 15, 't': 75},
    'showactive': False,
    'type': 'buttons',
    'x': 0.1,
    'xanchor': 'right',
    'y': 0,
    'yanchor': 'top'
}

sliders_dict = {
    'active': 20,
    'yanchor': 'top',
    'xanchor': 'left',
    'currentvalue': {
        'font': {'size': 20},
        'prefix': 'Monthly child allowance: ',
        'visible': True,
        'xanchor': 'right'
    },
    'transition': {'duration': 300, 'easing': 'cubic-in-out'},
    'pad': {'b': 10, 't': 50},
    'len': 0.9,
    'x': 0.1,
    'y': 0,
    'steps': []
}

steps = []
for ca in ca_amts:
    slider_step = {
        'args': [
            [ca],
            {'frame': {'duration': 300, 'redraw': True},
             'mode': 'immediate',
             'transition': {'duration': 300}}
        ],
        'label': '$' + str(ca),
        'method': 'animate'
    }
    steps.append(slider_step)
sliders_dict['steps'] = steps

# create frames for a given state and funding method
def make_frames(state, funding):
    raw_data = deciles[(deciles.state == state) &
                       (deciles.funding == funding)].round()
    frames = {}
    for ca in ca_amts:
        frames[str(ca)] = list(raw_data[raw_data.monthly_ca == ca].net_chg)
    return frames

# create dataframe of booleans to determine trace visibility
# separating funding mechanisms is currently redundant but can 
#    in theory be used to add another dropdown menu
n = len(state_names) * len(fundings)
frames_list = []
count = 0
visible = []
for state in state_names:
    vis_list = []
    for funding in fundings:
        frames_list.append(make_frames(state, funding))
        v = np.array([False] * n)
        v[count] = True
        if state == 'US' and funding != 'fed':
            v[count] = False
        vis_list.append(v)
        count += 1
    visible.append(vis_list)
visible = pd.DataFrame(visible, columns = fundings, index = state_names)

# add traces to figure dictionary
for i in range(n):
    data_dict = {
        'x': x,
        'y': None if i > 2 else frames_list[i]['500'],
        'type': 'bar',
        'visible': True if i == 1 else ('legendonly' if i < 3 else False),
        'name': fundings[i % 3],
        'marker_color':  colors[i % 3]
    }
    fig_dict['data'].append(data_dict)

# reorder existing frames
frames = []
for ca in ca_amts:
    data_list = []
    for f in frames_list:
        data_list.append({'y': f[str(ca)], 'type': 'bar'})
    frame = {'data': data_list, 'name': str(ca), 'traces': list(range(n))}
    frames.append(frame)

# add additional features to figure dictionary
fig_dict['frames'] = frames
fig_dict['layout']['sliders'] = [sliders_dict]

# generate plotly figure
fig = go.Figure(fig_dict)

# generate dropdown menu buttons
buttons = []
for state in state_names:
    new_button = {'method': 'update',
                  'label': state,
                  'args': [{'visible': (visible['fed'][state] | 
                                        visible['deficit'][state] |
                                        visible['state'][state])},
                           {'title': 'Average net change to household ' +
                            'income by decile in ' + state}
                          ]}
    buttons.append(new_button)
    
# construct button menu
updatemenus = {'buttons': buttons,
                'direction': 'down',
                'showactive': True,
                'pad':{"r": 10, 't': 20},
                'xanchor': 'left',
                'yanchor': 'top',
                'x': 0,
                'y': 1.2
               }

# add slider and button menus
fig.update_layout(updatemenus=[slider_menu, updatemenus])

# display figure
fig.show(config={'displayModeBar': False})

The Gini coefficient is another tool to calculate a policy reform’s impact on inequality. It lies between 0 and 1, with 0 indicating that everyone has the exact same income, and 1 indicating that one person possesses all the income.

Across funding strategies, child allowances reduce inequality as measured by the Gini coefficient, with larger child allowances producing larger inequality reductions. Nationally, a $500 monthly child allowance shrinks the Gini coefficient nine percent, from 0.446 to 0.406. At the state level, current Gini coefficients vary, but a $200 monthly child allowance tends to cut inequality between 4 and 5 percent.

# data labels
GINI = {'fed_gini': 'Federal tax',
        'state_gini': 'State tax',
        'non_funded_gini': 'No funding'}

# reformat data
data_list = []
for state in state_names:
    state_data = tax[tax.state == state]
    state_list = []
    for gini in GINI:
        state_list.append(state_data[gini])
    data_list.append(state_list)

data_columns = list(GINI.keys())
data = pd.DataFrame(data_list, columns = data_columns)
data['State'] = state_names
data = data.set_index('State')

def getDataList(state):
    data_list = []
    for dc in data_columns:
        data_list.append(data.loc[state][dc])
    return data_list

# initialize figure
fig = go.Figure()

# add traces
x = tax.child_allowance.unique()
for gini in GINI:
    fig.add_trace(go.Scatter(
        x=x, 
        y=tax[tax.state == default_state][gini],
        name=GINI[gini],
        marker = dict(color = COLOR_MAP[GINI[gini]])
    ))

# generate buttons
buttons = []
for state in state_names:
    new_button = {'method': 'update',
                  'label': state,
                  'args': [{'y': getDataList(state),
                           'visible': [True,
                                       'legendonly' if state == 'US' else True,
                                       True]},
                           {'title': 'Income inequality in ' + state}
                          ]}
    buttons.append(new_button)
    
# construct menus
updatemenus = [{'buttons': buttons,
                'direction': 'down',
                'showactive': True,
                'pad':{'l': 10, 'r': 25},
               }]

# update layout with buttons, and show the figure
fig.update_layout(updatemenus=updatemenus)

fig.update_xaxes(title_text='Monthly child allowance')

gini_values = tax.non_funded_gini.tolist() + tax.fed_gini.tolist() + tax.state_gini.tolist()
ymin = math.floor(min(gini_values) * 100) / 100
ymax = math.ceil(max(gini_values) * 100) / 100
fig.update_yaxes(title_text='Gini index of per-capita income',
                 range=[ymin, ymax])

fig.update_layout(height=600, 
                  margin=dict(l=0, r=0, t=80, b=0),
                  font=dict(family='Roboto'),
                  hovermode='x', 
                  xaxis_tickprefix='$',
                  xaxis_ticksuffix='',
                  plot_bgcolor='white',
                  legend_title_text='',
                  title={
                    'text': 'Income inequality in ' + default_state,
                    'y':0.95,
                    'x':0.01,
                    'xanchor': 'left',
                    'yanchor': 'top'}
                 )

fig.update_traces(mode='markers+lines', hovertemplate=None)

# hide state tax rate for US only
hide_line = ['State tax']
fig.for_each_trace(lambda trace: trace.update(visible="legendonly")
                   if trace.name in hide_line else ())

fig.show(config={'displayModeBar': False})

A child allowance can also substantially cut poverty. In this example, a person is said to be in poverty if their household’s total post tax and transfer income is less than their poverty threshold. Poverty thresholds are determined by the Census Bureau’s Supplemental Poverty Measure (SPM), which considers a medley of factors including household size, housing status, and local cost of living.

# data labels
FUNDING = {'fed_poverty_rate': 'Federal tax',
           'state_poverty_rate': 'State tax',
           'non_funded_poverty_rate': 'Deficit'}

ca_amts = summary.child_allowance.unique()
child_poverty = summary[(summary['age_group'] == 'child') &
                        (summary['race'] == 'All')]

# create figure dictionary
fig_dict = {
    'data': [],
    'layout': {},
    'frames': []
}

# fill in most of layout
fig_dict['layout'] = {
    'plot_bgcolor': 'white',
    'font': dict(family = 'Roboto'),
    'height': 600,
    'margin': dict(t=100, b=0, l=0, r=10)
}
fig_dict['layout']['title'] = {
    'text': ('Child poverty by state with ' + 
             FUNDING[list(FUNDING.keys())[0]].lower() + 
             ' funded child allowance'),
    'y': 0.97,
    'x': 0.05,
    'xanchor': 'left',
    'yanchor': 'top'
}

# add slider specifications
slidermenu =  {
    'buttons': [
        {
            'args': [None, {'frame': {'duration': 500, 'redraw': True},
                            'fromcurrent': True,
                            'transition': {'duration': 300,
                                           'easing': 'quadratic-in-out'}}],
            'label': '&#9654;',
            'method': 'animate'
        },
        {
            "args": [[None], {"frame": {"duration": 0, "redraw": True},
                              "mode": "immediate",
                              "transition": {"duration": 0}}],
            "label": "&#9724;",
            "method": "animate"
        }
    ],
    'direction': 'left',
    'pad': {'r': 15, 't': 75},
    'showactive': True,
    'type': 'buttons',
    'x': 0.1,
    'xanchor': 'right',
    'y': 0,
    'yanchor': 'top'
}
    
sliders_dict = {
    'active': 0,
    'yanchor': 'top',
    'xanchor': 'left',
    'currentvalue': {
        'font': {'size': 20},
        'prefix': 'Monthly child allowance: ',
        'visible': True,
        'xanchor': 'right'
    },
    'transition': {'duration': 300, 'easing': 'cubic-in-out'},
    'pad': {'b': 10, 't': 50},
    'len': 0.9,
    'x': 0.1,
    'y': 0,
    'steps': []
}

steps = []
for ca in ca_amts:
    slider_step = {
        'args': [
            [ca],
            {'frame': {'duration': 300, 'redraw': True},
             'mode': 'immediate',
             'transition': {'duration': 300}}
        ],
        'label': '$' + str(ca),
        'method': 'animate'
    }
    steps.append(slider_step)
sliders_dict['steps'] = steps

# generate frames
frames = []
locations = child_poverty.code
zero_poverty = child_poverty[child_poverty.child_allowance == 0]
for ca in ca_amts:
    data_list = []
    ca_data = child_poverty[child_poverty.child_allowance == ca]
    for funding in FUNDING:
        data_list.append({
            'hovertemplate': 
                'State: %{location}' + 
                '<br>Poverty rate: %{z}<br>' + 
                'Poverty reduction: %{customdata} pp' +
                '<extra></extra>',
            'locationmode': 'USA-states',
            'locations': child_poverty.code.unique(),
            'z': ca_data[funding].tolist(), 
            'type': 'choropleth',
            'text': 'hello:',
            'customdata': list(map(lambda x,y: round(x-y, 2),
                                   zero_poverty[funding], ca_data[funding]))
        })
    
    frame = {'data': data_list, 'name': str(ca), 'traces': [0,1,2]}
    frames.append(frame)
    
# add frames to figure dictionary
fig_dict['frames'] = frames

# add traces to figure dictionary
for i in (range(len(FUNDING))):
    fig_dict['data'].append(frames[0]['data'][0])

# generate figure
fig = go.Figure(fig_dict)

# generate dropdown menu buttons
buttons = []
for funding in FUNDING:
    new_button = {'method': 'update',
                  'label': FUNDING[funding],
                  'args': [{'visible': [f == funding for f in FUNDING.keys()]},
                           {'title': 'Child poverty by state with ' + 
                            FUNDING[funding] + ' funded child allowance'}
                          ]}
    buttons.append(new_button)
    
# construct button menu
updatemenu = {'buttons': buttons,
              'direction': 'down',
              'showactive': True,
              'pad':{"r": 10, 't': 20, 'l': 50},
              'xanchor': 'left',
              'yanchor': 'top',
              'x': 0,
              'y': 1.2
             }

# add slider, dropdown menu, and set geo scope
fig.update_layout(
    geo_scope='usa', # limite map scope to USA
    sliders=[sliders_dict],
    updatemenus=[slidermenu, updatemenu]
)

# update visual attributes
fig.update_traces(showscale=False, colorscale='Reds', zmin=0, zmax=22)
fig.update_layout(
    hoverlabel=dict(
        bgcolor="white",
        font_size=16,
        font_family="Rockwell"
    )
)
fig.update(layout_showlegend=False)

fig.show(config={'displayModeBar': False})

Poverty by race

The next set of charts show how different demographics are impacted by each reform. Across states, a $300 monthly child allowance cuts child poverty by about half and narrows the gap between Black and White child poverty within a few percentage points.

FUNDING = {'fed_poverty_rate': 'Federal tax',
           'state_poverty_rate': 'State tax',
           'non_funded_poverty_rate': 'No funding'}

# initial data set-up 
race = summary[summary['age_group'] == 'child']
x = race.race.unique()
x.sort()
ca_amts = race.child_allowance.unique()
state_names = race.state.unique()
state_names = np.insert(state_names[:-1], 0, 'US')

# create figure dictionary
fig_dict = {
    'data': [],
    'layout': {},
    'frames': []
}

# fill in most of layout
fig_dict['layout'] = {
    'plot_bgcolor': 'white',
    'font': dict(family = 'Roboto'),
    'showlegend': True,
    'height': 600,
    'margin': dict(t=100, b=0, l=0, r=0)
}
fig_dict['layout']['title'] = {
    'text': 'Poverty by race in US', 
    'y': 0.97,
    'x': 0.05,
    'xanchor': 'left',
    'yanchor': 'top'
}
fig_dict['layout']['xaxis'] = {
    'title': 'Race', 
    'type': 'category'
}
fig_dict['layout']['yaxis'] = {
    'title': 'Poverty rate', 
    'ticksuffix': '%',
    'range': [0, 25]
}

# add slider specifications
slider_menu =  {
    'buttons': [
        {
            'args': [None, {'frame': {'duration': 500, 'redraw': True},
                            'fromcurrent': True, 
                            "mode": "immediate",
                            'transition': {'duration': 300,
                                           'easing': 'quadratic-in-out'}}],
            'label': '&#9654;',
            'method': 'animate'
        },
        {
            "args": [[None], {"frame": {"duration": 0, "redraw": True},
                              "transition": {"duration": 0}}],
            "label": "&#9724;",
            "method": "animate"
        }
    ],
    'direction': 'left',
    'pad': {'r': 15, 't': 75},
    'showactive': False,
    'type': 'buttons',
    'x': 0.1,
    'xanchor': 'right',
    'y': 0,
    'yanchor': 'top'
}

sliders_dict = {
    'active': 0,
    'yanchor': 'top',
    'xanchor': 'left',
    'currentvalue': {
        'font': {'size': 20},
        'prefix': 'Monthly child allowance: ',
        'visible': True,
        'xanchor': 'right'
    },
    'transition': {'duration': 300, 'easing': 'cubic-in-out'},
    'pad': {'b': 10, 't': 50},
    'len': 0.9,
    'x': 0.1,
    'y': 0,
    'steps': []
}

steps = []
for ca in ca_amts:
    slider_step = {
        'args': [
            [ca],
            {'frame': {'duration': 300, 'redraw': True},
             'mode': 'immediate',
             'transition': {'duration': 300}}
        ],
        'label': '$' + str(ca),
        'method': 'animate'
    }
    steps.append(slider_step)
sliders_dict['steps'] = steps

# create frames for a given state and funding method
def make_frames(state, funding):
    raw_data = race[(race.state == state)]
    frames = {}
    for ca in ca_amts:
        frames[str(ca)] = list(raw_data[raw_data.child_allowance == ca].sort_values('race')[funding])
    return frames

# create dataframe of booleans to determine trace visibility
n = len(state_names) * len(FUNDING)
frames_list = []
count = 0
visible = {}
for state in state_names:
    v = [False] * n
    for funding in FUNDING:
        frames_list.append(make_frames(state, funding))
        v[count] = True
        count += 1
    visible[state] = v + v
v = [False] * n
v[0] = True
v[1] = 'legendonly'
v[2] = 'legendonly'
visible['US'] = v + v

# reorder existing frames
frames = []
for ca in ca_amts:
    data_list = []
    count = 0
    for f in frames_list:
        data_list.append({
            'y': f['0'], 
            'x': x,
            'type': 'bar', 
            'offsetgroup': count, 
            'showlegend': False,
            'legendgroup': count,
            'marker_color': GRAY_SHADOW,
            'name': 'No Child Allowance'
        })
        count += 1
    count = 0
    for f in frames_list:
        data_list.append({
            'y': f[str(ca)], 
            'x': x,
            'type': 'bar', 
            'offsetgroup': count,
            'legendgroup': count,
            'name': list(FUNDING.values())[count % 3],
            'marker_color': COLOR_MAP[list(FUNDING.values())[count % 3]]
        })
        count += 1
    frame = {'data': data_list, 'name': str(ca), 'traces': list(range(n*2))}
    frames.append(frame)

# add additional features to figure dictionary
fig_dict['frames'] = frames
fig_dict['layout']['sliders'] = [sliders_dict]

for i in range(n):
    data_dict = frames[0]['data'][i]
    if i < 3:
        data_dict['visible'] = True
    else:
        data_dict['visible'] = False
    fig_dict['data'].append(data_dict)
for i in range(n):
    data_dict = frames[0]['data'][n + i]
    if i < 3:
        data_dict['visible'] = True
    else:
        data_dict['visible'] = False
    fig_dict['data'].append(data_dict)

# generate plotly figure
fig = go.Figure(fig_dict)

# generate dropdown menu buttons
buttons = []
for state in state_names:
    new_button = {'method': 'update',
                  'label': state,
                  'args': [{'visible': (visible[state])},
                           {'title': 'Poverty by race in ' + state}
                          ]}
    buttons.append(new_button)
    
# construct button menu
updatemenus = {'buttons': buttons,
               'direction': 'down',
               'showactive': True,
               'pad':{"r": 10, 't': 20},
               'xanchor': 'left',
               'yanchor': 'top',
               'x': 0,
               'y': 1.2
              }

# add slider and button menus
fig.update_layout(updatemenus=[slider_menu, updatemenus])

# display figure
fig.show(config={'displayModeBar': False})

Together, these figures show how a child allowance can accomplish its initial purpose of reducing child poverty while also decreasing adult poverty and abating inequality.

Currently, the closest thing America has to a child allowance is the Child Tax Credit which provides up to $2,000 per child to eligible families. Yet over one-third of children in the U.S are ineligible for the full child tax credit because their families don’t earn enough to qualify, and another one-tenth are excluded because their families earn too much.

The charts above reflect the opportunity for federal legislation to reduce child poverty across states, as well as states’ opportunity to reduce child poverty with truly universal child allowances of their own. This data can be used to advocate for the expansion of child allowances and fully refundable tax credits to reduce poverty and prioritize the well-being of children.